package com.perceptivesoftware.licensing.client.common.util;

import com.google.gwt.user.client.rpc.IsSerializable;

/*
 * PerceptivePermission represents one single permission. It does not include the user/role/dept the permission
 * pertains to, as it is designed to be used as a representation of what permissions the current user has.
 * It is designed to be used in conjunction with PerceptivePermissions (which is a DTO stored in KwUservalDTO)
 * to tell the UI & server what permissions the current user has.
 *
 * PerceptivePermission is designed in a way that it can be used as a multi-key index, due to the fact that the
 * overriden .equals() method compares each key to ensure they are the same value.
 *
 * Adding a "Key":
 * To add a key to PerceptivePermission, you must:
 * 1) add it as a private value
 * 2) modify the only constructor so the value will always be set and old calls to
 *    the constructor can be reviewed to make sure nothing else needs to be changed
 * 3) modify the .equals() method to check the new variable for equality.
 * 4) modify the .hashCode() method to consider the new variable. Concatenate it to the end of String s.
 * 5) Add private getters/setters for the value so it can be serialized.
 *
 */
public class PerceptivePermission implements IsSerializable
{
	private NPType type;
	private NPAction action;
	private String itemCode;
	private Boolean hasPermission;
	private Boolean databasePermissionValue;
	private Boolean hasChangedForCascade;

	@SuppressWarnings("unused")
	// For Serialization
	private PerceptivePermission()
	{

	}

	public PerceptivePermission(final NPType type, final NPAction action)
	{
		this.type = type;
		this.action = action;
		databasePermissionValue = false;
		hasChangedForCascade = false;
	}

	public PerceptivePermission(final NPType type, final NPAction action, final Boolean hasPermission)
	{
		this(type, action);
		this.hasPermission = hasPermission;
		databasePermissionValue = hasPermission;
	}

	public PerceptivePermission(final NPType type, final NPAction action, final String itemCode)
	{
		this.type = type;
		this.action = action;
		if (itemCode != null && itemCode.equals("0"))
		{
			this.itemCode = null;
		}
		else
		{
			this.itemCode = itemCode;
		}
		databasePermissionValue = false;
		hasChangedForCascade = false;
	}

	public PerceptivePermission(final NPType type, final NPAction action, final String itemCode, final Boolean hasPermission)
	{
		this(type, action, itemCode);
		this.hasPermission = hasPermission;
		databasePermissionValue = hasPermission;
	}

	@Override
	public boolean equals(final Object o)
	{
		if (!(o instanceof PerceptivePermission))
		{
			return false;
		}
		final PerceptivePermission p = (PerceptivePermission) o;
		if (!action.equals(p.action))
		{
			return false;
		}
		if (!type.equals(p.type))
		{
			return false;
		}

		if (itemCode == null || p.itemCode == null) // if either one is null
		{
			if (itemCode != null || p.itemCode != null)
			{
				return false;
			}// (else they are both null and dont fail, but still skip the
				// compare below)
		}
		else if (!itemCode.equals(p.itemCode))
		{
			return false;
		}
		return true;
	}

	@Override
	public int hashCode()
	{
		final String s = "" + type + ":" + action + ":" + itemCode + ":";
		int hash = 17;
		hash = hash * 37 + s.hashCode();
		return hash;
	}

	public String getItemCode()
	{
		return itemCode;
	}

	@SuppressWarnings("unused")
	// for serialization
	private void setItemCode(final String itemCode)
	{
		this.itemCode = itemCode;
	}

	public NPType getType()
	{
		return type;
	}

	@SuppressWarnings("unused")
	// for serialization
	private void setType(final NPType type)
	{
		this.type = type;
	}

	public NPAction getAction()
	{
		return action;
	}

	@SuppressWarnings("unused")
	// for serialization
	private void setAction(final NPAction action)
	{
		this.action = action;
	}

	public Boolean getHasPermission()
	{
		return hasPermission;
	}

	public void setHasPermission(final Boolean hasPermission)
	{
		this.hasPermission = hasPermission;
	}

	@SuppressWarnings("unused")
	// for serialization
	private Boolean getDatabasePermissionValue()
	{
		return databasePermissionValue;
	}

	@SuppressWarnings("unused")
	// for serialization
	private void setDatabasePermissionValue(final Boolean databasePermissionValue)
	{
		this.databasePermissionValue = databasePermissionValue;
	}

	public boolean isDirty()
	{
		return !hasPermission.equals(databasePermissionValue);
	}

	public String whyDirty()
	{
		final StringBuffer sb = new StringBuffer();
		sb.append(type);
		sb.append(":");
		sb.append(action);
		sb.append(":");
		if (itemCode != null)
		{
			sb.append(itemCode);
			sb.append(":");
		}
		sb.append("From ");
		if (databasePermissionValue)
		{
			sb.append("true");
		}
		else
		{
			sb.append("false");
		}
		sb.append(" to ");
		if (hasPermission)
		{
			sb.append("true");
		}
		else
		{
			sb.append("false");
		}
		return sb.toString();
	}

	public void savedToDatabase()
	{
		databasePermissionValue = hasPermission;
		hasChangedForCascade = false;
	}

	public void setHasChangedForCascade(final Boolean hasChangedForCascade)
	{
		this.hasChangedForCascade = hasChangedForCascade;
	}

	public boolean getHasChangedForCascade()
	{
		return hasChangedForCascade;
	}

}
